//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<CCompositeTexture.cpp>
///	@path	~/src/gui/composite/
///	@date	2008/09/09
///	@brief	.

#define _FULLAPI
#include "config/config.h"

#include "lib/utilities/time.h"

#include "graphics/DxHelpers.h"
#include "graphics/IRenderer.h"
#include "gui/composite/CCompositeTexture.h"

namespace xeres {

	IMPL_IOBJECT_CLASS( CCompositeTexture );

	// CCompositeTexture
	CCompositeTexture::CCompositeTexture( void )
	{
	}

	// ~CCompositeTexture
	CCompositeTexture::~CCompositeTexture( void )
	{
	}

	// GetType
	TextureType CCompositeTexture::GetType( void )
	{
		return m_texture->GetType();
	}
	
	// GetFormat
	DXFormat CCompositeTexture::GetFormat( void )
	{
		return m_texture->GetFormat();
	}

	// GetSize
	Pair<int> CCompositeTexture::GetSize( void )
	{
		if( m_texture.IsValid() )
		{
			return m_texture->GetSize();
		}
		return Pair<int>( 0 , 0 );
	}

	// GetDepth
	size_t CCompositeTexture::GetDepth( void )
	{
		return m_texture->GetDepth();
	}

	// Map
	bool CCompositeTexture::Map( uint sub , ResourceMap& data )
	{
		return m_texture->Map( sub , data );
	}

	// ReadBack
	bool CCompositeTexture::ReadBack( uint sub , ResourceMap& data , bool readonly )
	{
		return m_texture->ReadBack( sub , data , readonly );
	}

	// Unmap
	bool CCompositeTexture::Unmap( uint sub )
	{
		return m_texture->Unmap( sub );
	}

	// IsWritable
	bool CCompositeTexture::IsWritable( void )
	{
		return m_texture->IsWritable();
	}

	// IsReadable
	bool CCompositeTexture::IsReadable( void )
	{
		return m_texture->IsReadable();
	}

	// Reset
	bool CCompositeTexture::Reset( RefWeak<IRenderer> renderer , const Pair<int>& size , bool update )
	{
		// Release texture, it will be delete by resource manage later.
		m_texture = NULL;

		// create new
		m_texture = renderer->CreateTextureForSprite( size.x , size.y );
		if( m_texture.IsNull() )
		{
			return false;
		}

		m_color = renderer->GetColorOrder();

		// setup layer
		m_layer.Resize( size.x , size.y );

		if( update )
			Update( Rect<int>(0,0,size.x,size.y) );

		return true;
	}

	// Update
	void CCompositeTexture::Update( const Rect<int>& r )
	{
		// lock texture
		const Pair<int> size = m_texture->GetSize();
		const Rect<int> rect( 0 , 0 , size );
		Rect<int> region = rect & r;

		if( region.is_empty() )
			return;
		
		ResourceMap data;

		bool result = m_texture->Map( 0 , data );

		if( !result )
		{
			TRACE_ERROR( _S("CLayeredCanvas::Update: Failed to lock texture for update.") );
			return;
		}

		if( m_color == COLOR_ORDER_RGBA )
		{
			byte * locked = data.GetData();
			byte * dst = (byte*)m_layer.GetPixelInvert( 0 , 0 );
			const size_t layerPitch = m_layer.GetWidth() * sizeof(ARGB);
			const size_t regionPitch = ( size.x ) * sizeof(ARGB);

			for( int y = 0 ; y < size.y ; ++y )
			{
				int * write = (int*)(locked + data.GetRowPitch() * y);
				int * start = (int*)(dst - layerPitch * y);
				for( int x = 0 ; x < size.x ; ++ x )
				{
					write[x] = d3d_convert_color( start[x] );
				}
			}
		}
		else
		{
			byte * locked = data.GetPixel( region.left() , region.top() );
			byte * dst = (byte*)m_layer.GetPixelInvert( region.left() , region.top() );
			const size_t layerPitch = m_layer.GetWidth() * sizeof(ARGB);
			const size_t regionPitch = ( region.width() ) * sizeof(ARGB);

			for( int i = 0 , total = region.height() ; i < total ; ++i )
			{
				byte * write = locked + data.GetRowPitch() * i;
				byte * start = dst - layerPitch * i;
				memcpy( write , start , regionPitch );
			}
		}

		// unlock
		m_texture->Unmap( 0 );
	}

	// Update
	bool CCompositeTexture::Update( uint sub , const Box<uint>& size , const byte * data , uint row_pitch , uint depth_pitch )
	{
		return false;
	}
	// OnLostDevice
	bool CCompositeTexture::OnLostDevice( void )
	{
		return true;
	}
	// OnResetDevice
	bool CCompositeTexture::OnResetDevice( RefWeak<IDevice> device )
	{
		return true;
	}
	// GetTextureInterface
	IUnknown * CCompositeTexture::GetTextureInterface( void )
	{
		if( m_texture.IsValid() )
		{
			return m_texture->GetTextureInterface();
		}
		return NULL;
	}

//#pragma comment( linker , "/defaultlib:d3dx9d.lib" )

	// save
	void CCompositeTexture::Save( void )
	{
		//D3DXSaveSurfaceToFile( L"composite.png" , D3DXIFF_PNG , m_surf , NULL , NULL );
		//D3DXSaveTextureToFile( L"composite.png" , D3DXIFF_PNG , (IDirect3DTexture9*)m_texture->GetHandle() , NULL );
	}
	
} // namespace xeres
